#ifndef _PARTICLE_SYSTEM_
#define _PARTICLE_SYSTEM_

#include "cuda_runtime_api.h"
#include "cutil_math.h"

#include "SimParameters.h"

/******************************************************************************
 *  CLASS PARTICLE SYSTEM
 *  
 *  This classe holds the entire physics system. It's methods are implemented
 * part in a .cpp file and part in a .cu file.
 *  If a method does not use any CUDA specific keyword, it should be implmented
 * in the cpp file, because debugging does not work well in pure c++ code on a
 * file compiled by nvcc.
 *****************************************************************************/
class ParticleSystem
{
public:
    /**
     *  CONSTRUCTOR (C++)
     *  
     *  Sets the initial state of the particle system.
     */
    ParticleSystem();

    /** Keeps the current number of particles in the simulation */
    int numParticles;

    // on .cu
    /**
     *  Initialize CUDA Arrays (CUDA)
     *
     *  This functions allocates the global arrays used by the system:
     *  Radius array on constant memory;
     *  Double Position arrays on global memory;
     *  Double Velocity arrays on global memory;
     *  Double Force arrays on global memory.
     */
    void initCudaArrays();

    /**
     *  Update (CUDA)
     *
     *  This function updates de 3 global arrays trough the Euler method.
     *
     *  @param: dt is the amount of miliseconds used to calculate the passage
     * of time. In this simulation dt, is a constant ( FIXED_TIME_STEP )
     */
    void update( float dt );

    /** arrays of particle attributes on CPU memory */
    float3* pPosition;
    float3* pVelocity;
    float3* pForce;
    float3* pColor;
    float*  pRadius;

    /** arrays of particle attributes on GPU memory */
    float3* devPosition;
    float3* devVelocity;
    float3* devForce;
    // double the buffers!
    float3* devPosition_2;
    float3* devVelocity_2;
    float3* devForce_2;

    /** 
     *  boolean that says which of the buffers are input.
     * TRUE, first arrays are input.
     * FALSE, second arrays are input.
     */
    bool buffOneInput;

private:
    /**
     *  Update Space Partition CUDA
     *
     *  This function will perform the update with the space partition method.
     */
    void updateSpacePartitionCuda( float dt );
};

#endif